use crate::base::Color;
use super::{cell::Cell, Coord};

pub struct Grid {
    cells: Vec<Vec<Cell>>,
    width: i32,
    height: i32,
}

impl Grid {
    pub fn new(width: i32, height: i32) -> Self {
        assert!(width > 0 && height > 0);
        Self {
            cells: vec![vec![Cell::Empty; width as usize]; height as usize],
            width,
            height,
        }
    }
}

impl Grid {
    pub fn width(&self) -> i32 {
        self.width
    }

    pub fn height(&self) -> i32 {
        self.height
    }

    pub fn cell(&self, coord: Coord) -> Option<Cell> {
        if self.is_valid_coord(coord) {
            let (x, y) = coord.xy();
            Some(self.cells[y as usize][x as usize])
        } else {
            None
        }
    }

    pub fn set_cell(&mut self, coord: Coord, c: Cell) {
        assert!(
            self.is_valid_coord(coord),
            "'{:?}' is not a valid coord",
            coord
        );
        let (x, y) = coord.xy();
        self.cells[y as usize][x as usize] = c;
    }

    pub fn set_cell_obstacle(&mut self, coord: Coord) {
        assert!(
            self.is_valid_coord(coord),
            "'{:?}' is not a valid coord",
            coord
        );
        let (x, y) = coord.xy();
        self.cells[y as usize][x as usize] = Cell::Routed(Color::black());
    }

    pub fn is_valid_coord(&self, coord: Coord) -> bool {
        let (x, y) = coord.xy();
        if x < 0 || x >= self.width || y < 0 || y >= self.height {
            false
        } else {
            true
        }
    }
}
